import type { GraphicObject } from './GraphicObject';
import type { BoundingBox, Point, ViewTransform } from './types';

export class ViewController {
  private viewTransform: ViewTransform;
  private canvas: HTMLCanvasElement;

  constructor(canvas: HTMLCanvasElement, initialTransform?: ViewTransform) {
    this.canvas = canvas;
    this.viewTransform = initialTransform || this.defaultViewTransform();
  }

  /**
   * 视图平移
   */
  pan(delta: Point): void {
    this.viewTransform.offset.x += delta.x;
    this.viewTransform.offset.y += delta.y;
  }

  /**
   * 视图缩放
   */
  zoom(factor: number, center?: Point): void {
    const zoomCenter = center || this.getCanvasCenter();

    // 保存当前缩放前的偏移量
    const oldOffset = { ...this.viewTransform.offset };

    // 更新缩放比例
    this.viewTransform.scale *= factor;

    // 限制缩放范围
    this.viewTransform.scale = Math.max(
      0.01,
      Math.min(100, this.viewTransform.scale),
    );

    // 调整偏移量以保持缩放中心不变
    const scaleRatio = factor;
    this.viewTransform.offset.x =
      zoomCenter.x - (zoomCenter.x - oldOffset.x) * scaleRatio;
    this.viewTransform.offset.y =
      zoomCenter.y - (zoomCenter.y - oldOffset.y) * scaleRatio;
  }

  /**
   * 视图旋转
   */
  rotate(angle: number): void {
    this.viewTransform.rotation += angle;
    // 保持角度在 0-2π 范围内
    this.viewTransform.rotation = this.viewTransform.rotation % (2 * Math.PI);
  }

  /**
   * 屏幕坐标转换为世界坐标
   */
  screenToWorld(screenPoint: Point): Point {
    // 考虑Canvas的CSS尺寸和实际尺寸的差异
    const rect = this.canvas.getBoundingClientRect();
    const scaleX = this.canvas.width / rect.width;
    const scaleY = this.canvas.height / rect.height;

    // 转换为Canvas坐标
    const canvasPoint = {
      x: (screenPoint.x - rect.left) * scaleX,
      y: (screenPoint.y - rect.top) * scaleY,
    };

    // 应用视图变换的逆变换
    const cos = Math.cos(-this.viewTransform.rotation);
    const sin = Math.sin(-this.viewTransform.rotation);

    const dx = canvasPoint.x - this.viewTransform.offset.x;
    const dy = canvasPoint.y - this.viewTransform.offset.y;

    return {
      x: (dx * cos - dy * sin) / this.viewTransform.scale,
      y: (dx * sin + dy * cos) / this.viewTransform.scale,
    };
  }

  /**
   * 世界坐标转换为屏幕坐标
   */
  worldToScreen(worldPoint: Point): Point {
    // 应用视图变换
    const cos = Math.cos(this.viewTransform.rotation);
    const sin = Math.sin(this.viewTransform.rotation);

    const x = worldPoint.x * this.viewTransform.scale;
    const y = worldPoint.y * this.viewTransform.scale;

    const canvasPoint = {
      x: this.viewTransform.offset.x + x * cos - y * sin,
      y: this.viewTransform.offset.y + x * sin + y * cos,
    };

    // 转换为屏幕坐标
    const rect = this.canvas.getBoundingClientRect();
    const scaleX = rect.width / this.canvas.width;
    const scaleY = rect.height / this.canvas.height;

    return {
      x: rect.left + canvasPoint.x * scaleX,
      y: rect.top + canvasPoint.y * scaleY,
    };
  }

  /**
   * 重置视图
   */
  resetView(): void {
    this.viewTransform = this.defaultViewTransform();
  }

  /**
   * 适应视图到对象
   */
  fitToView(objects: GraphicObject[]): void {
    if (objects.length === 0) {
      this.resetView();
      return;
    }

    // 计算所有对象的边界框
    let minX = Infinity,
      maxX = -Infinity;
    let minY = Infinity,
      maxY = -Infinity;

    for (const obj of objects) {
      const bbox = obj.getBoundingBox();
      minX = Math.min(minX, bbox.x);
      maxX = Math.max(maxX, bbox.x + bbox.width);
      minY = Math.min(minY, bbox.y);
      maxY = Math.max(maxY, bbox.y + bbox.height);
    }

    // 添加边距
    const margin = 20;
    const width = maxX - minX + margin * 2;
    const height = maxY - minY + margin * 2;

    // 计算合适的缩放比例
    const scaleX = this.canvas.width / width;
    const scaleY = this.canvas.height / height;
    const scale = Math.min(scaleX, scaleY) * 0.9; // 90% 填充

    // 计算中心点偏移
    const centerX = (minX + maxX) / 2;
    const centerY = (minY + maxY) / 2;

    this.viewTransform = {
      offset: {
        x: this.canvas.width / 2 - centerX * scale,
        y: this.canvas.height / 2 - centerY * scale,
      },
      scale: scale,
      rotation: 0,
    };
  }

  /**
   * 获取当前视图变换
   */
  getViewTransform(): ViewTransform {
    return { ...this.viewTransform };
  }

  /**
   * 设置视图变换
   */
  setViewTransform(transform: ViewTransform): void {
    this.viewTransform = { ...transform };
  }

  /**
   * 获取Canvas中心点
   */
  private getCanvasCenter(): Point {
    return {
      x: this.canvas.width / 2,
      y: this.canvas.height / 2,
    };
  }

  /**
   * 默认视图变换
   */
  private defaultViewTransform(): ViewTransform {
    return {
      offset: { x: 0, y: 0 },
      scale: 1,
      rotation: 0,
    };
  }

  /**
   * 获取视图边界框
   */
  getViewBounds(): BoundingBox {
    const topLeft = this.screenToWorld({ x: 0, y: 0 });
    const bottomRight = this.screenToWorld({
      x: this.canvas.width,
      y: this.canvas.height,
    });

    return {
      x: topLeft.x,
      y: topLeft.y,
      width: bottomRight.x - topLeft.x,
      height: bottomRight.y - topLeft.y,
    };
  }

  /**
   * 检查点是否在视图内
   */
  isPointInView(worldPoint: Point): boolean {
    const bounds = this.getViewBounds();
    return (
      worldPoint.x >= bounds.x &&
      worldPoint.x <= bounds.x + bounds.width &&
      worldPoint.y >= bounds.y &&
      worldPoint.y <= bounds.y + bounds.height
    );
  }
}

export default ViewController;
